package nio.base;

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.concurrent.CountDownLatch;

public class FileChannelLockTest {

    @Test
    public void lock() throws IOException, InterruptedException {

        try (
                RandomAccessFile file = new RandomAccessFile("read.txt", "rw");
                FileChannel channel = file.getChannel();
        ) {

            final FileLock lock = channel.lock();
            System.out.println("lock得到锁");
            CountDownLatch count = new CountDownLatch(1);
            new Thread() {
                public void run() {
                    try {
                        try {
                            Thread.sleep(10000);
                        } finally {
                            lock.release();
                        }
                        System.out.println("lock释放");
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            count.await();
        }
    }

    //经测试，lock之后，其他进程无法访问lock文件，不同进程会阻塞
    @Test
    public void lock2() throws IOException, InterruptedException {

        try (
                RandomAccessFile file = new RandomAccessFile("read.txt", "rw");
                FileChannel channel = file.getChannel();
        ) {

            final FileLock lock = channel.lock();
            System.out.println("lock2得到锁");
            CountDownLatch count = new CountDownLatch(1);
            new Thread() {
                public void run() {
                    try {
                        try {
                            Thread.sleep(10000);
                        } finally {
                            lock.release();
                        }
                        System.out.println("lock2释放");
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            count.await();
        }
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        try (
                RandomAccessFile file = new RandomAccessFile("read.txt", "rw");
                RandomAccessFile file2 = new RandomAccessFile("read.txt", "rw");
                FileChannel channel = file.getChannel();
                FileChannel channel2 = file2.getChannel();
        ) {

            final FileLock lock = channel.lock();
            final FileLock lock2 = channel2.lock();
            System.out.println("得到锁");
            CountDownLatch count = new CountDownLatch(1);
            new Thread() {
                public void run() {
                    try {
                        try {
                            Thread.sleep(10000);
                        } finally {
                            lock.release();
                            lock2.release();
                        }
                        System.out.println("lock释放");
                        count.countDown();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
            count.await();
        }
    }

    //获取文件基本信息和删除文件测试
    @Test
    public void file1() throws IOException, InterruptedException {

        File f = new File("read.txt");
        try (
                RandomAccessFile file = new RandomAccessFile(f, "rw");
        ) {
            System.out.println(f.canExecute());
            System.out.println(f.canRead());
            System.out.println(f.canWrite());
            System.out.println(f.getAbsolutePath());
            System.out.println(f.getCanonicalPath());

            f.delete();
//			f.deleteOnExit();
        }
    }

    //经测试,同一进程内，lock并不会阻塞，而且直接报错
    @Test
    public void lockTest() throws IOException, InterruptedException {

        File f = new File("read.txt");
        try (
                RandomAccessFile file = new RandomAccessFile(f, "rw");
        ) {

            file.getChannel().lock();
            System.out.println("lock1");
            file.getChannel().lock();
            System.out.println("lock2");
        }
    }

    //经测试，同一进程内，tryLock也是直接报错，而不是返回null这么简单
    @Test
    public void tryLockTest() throws IOException, InterruptedException {

        File f = new File("read.txt");
        try (
                RandomAccessFile file = new RandomAccessFile(f, "rw");
        ) {

            file.getChannel().tryLock();
            System.out.println("lock1");
            file.getChannel().tryLock();
            System.out.println("lock2");
        }
    }

    //经测试，同一进程内，就算是同一个FileChannel的lock，tryLock也是直接报错，而不是返回null这么简单
    @Test
    public void tryLockTest2() throws IOException, InterruptedException {

        File f = new File("read.txt");
        try (
                RandomAccessFile file = new RandomAccessFile(f, "rw");
                FileChannel channel = file.getChannel();
        ) {
            channel.tryLock();
            System.out.println("lock1");
            channel.tryLock();
            System.out.println("lock2");
        }
    }
}
